package com.kalua.list.domainmodel.product;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import com.google.common.base.Objects;
import com.kalua.list.domainmodel.DomainModelUtil;
import com.kalua.list.domainmodel.MutablePersistentEntity;
import com.kalua.list.domainmodel.NumericId;
import com.kalua.list.domainmodel.TextIdentifier;

public class ProductImpl implements Product, MutablePersistentEntity<NumericId> {
	
	private static final long serialVersionUID = -2146718556735484374L;
	
	private NumericId id;
	private TextIdentifier retailerId;
	private TextIdentifier retailerIssuedId;
	private String name;
	private double price;
	private String fullImageURL;
	private String thumbnailImageURL;
	
	private Set<String> classifications;
	
	private NumericId batchCreated;
	private NumericId batchLastUpdated;
	
	public ProductImpl() {super();}
	
	public ProductImpl(	NumericId id, 
									TextIdentifier retailerId, 
									NumericId batchCreatedId, 
									TextIdentifier retailerIssuedId, 
									String name, double price,
									String fullImageURL, 
									String thumbnailImageURL) {
		this();
		setId(id);
		setRetailerId(retailerId);
		setBatchCreated(batchCreatedId);
		setRetailerIssuedId(retailerIssuedId);
		setName(name);
		setPrice(price);
		setFullImageURL(fullImageURL);
		setThumbnailImageURL(thumbnailImageURL);
		setClassifications(new HashSet<String>());		
	}	
	
	@Override
	public void updateTo(Product product) {
		setBatchLastUpdated(product.getBatchCreated());
		setName(product.getName());
		setPrice(product.getPrice());
		setFullImageURL(product.getFullImageURL());
		setThumbnailImageURL(product.getThumbnailImageURL());
		setClassifications(product.getClassifications());
	}

	@Override
	public void decodeHTTPRepresentation(){
		this.name = DomainModelUtil.decodeHttpString(this.name);
		this.classifications = DomainModelUtil.decodeHttpStrings(this.classifications);
	}
	
	@Override
	public NumericId getId() { return this.id; }
	@Override
	public void setId(NumericId existingId) { this.id= existingId;}
	
	@Override
	public TextIdentifier getRetailerIssuedId() { return this.retailerIssuedId; }
	public void setRetailerIssuedId(TextIdentifier retailerIssuedId) 
	{ this.retailerIssuedId = retailerIssuedId; }
	
	@Override
	public String getName() { return this.name; }
	public void setName(String name) { this.name = name; }
	
	@Override
	public double getPrice() { return this.price; }
	public void setPrice(double price) { this.price = price; }
	
	@Override
	public String getFullImageURL() { return this.fullImageURL; }
	public void setFullImageURL(String fullImageURL) { this.fullImageURL = fullImageURL; }

	@Override
	public String getThumbnailImageURL() { return this.thumbnailImageURL; }
	public void setThumbnailImageURL(String thumbnailImageURL) 
	{ this.thumbnailImageURL = thumbnailImageURL; }
	
	@Override
	public TextIdentifier getRetailerId() { return this.retailerId; }
	public void setRetailerId(TextIdentifier retailerId) { this.retailerId = retailerId; }

	@Override
	public NumericId getBatchCreated() { return this.batchCreated; }

	public void setBatchCreated(NumericId batchCreated) 
	{ this.batchCreated = batchCreated; }

	@Override
	public NumericId getBatchLastUpdated() { return this.batchLastUpdated; }
	public void setBatchLastUpdated(NumericId batchLastUpdated) 
	{ this.batchLastUpdated = batchLastUpdated; }

	public void addClassications(Set<String> classifications) 
	{ this.classifications.addAll(classifications); }
	
	@Override
	public Set<String> getClassifications() 
	{ return Collections.unmodifiableSet(this.classifications); }
	private void setClassifications(Set<String> classifications) 
	{ this.classifications = classifications; }

	@Override
	public int hashCode() {
		int result;
		if (this.id!=null)			
			result = id.hashCode();
		else if (this.retailerIssuedId!=null)
			result = Objects.hashCode(this.retailerIssuedId);
		else result = Objects.hashCode(this.name);		
		return result;
	}
	
	@Override
	public boolean equals(Object other) {
		boolean result = false;		
		if (this == other)
			result = true;
		else if (other!=null && getClass().isInstance(other)) {
			ProductImpl candidate = (ProductImpl)other;
			Object[] fields, otherFields;
			fields = new Object[]{	this.id,this.retailerIssuedId, this.name, this.price, 
												this.fullImageURL, this.thumbnailImageURL, 
												this.classifications, this.retailerId, this.batchCreated,
												this.batchLastUpdated};
				
			otherFields = new Object[]{	candidate.id,candidate.retailerIssuedId, candidate.name, 
														candidate.price, candidate.fullImageURL, 
														candidate.thumbnailImageURL, candidate.classifications, 
														candidate.retailerId, candidate.batchCreated,
														candidate.batchLastUpdated};
			result = Arrays.equals(fields, otherFields);
		}
		return result;
	}
	
	@Override
	public String toString() { return getName() + "  (" + getPrice() +")"; }

	public String toStringLong() {
		return "ProductImpl [id=" + id + "\n\tretailerIssuedId="
					+ retailerIssuedId + "\n\tfullImageURL=" + fullImageURL
					+ "\n\tthumbnailImageURL=" + thumbnailImageURL + "]";
	}
}